'use client';

import { zodResolver } from '@hookform/resolvers/zod';
import { usePathname, useRouter, useSearchParams } from 'next/navigation';
import { type Path, useForm } from 'react-hook-form';
import type { z } from 'zod';
import { Button } from '../ui/button';
import {
  Form,
  FormControl,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
} from '../ui/form';
import { Input } from '../ui/input';

export default function SearchFilter<T extends z.ZodType>({
  formItems,
  defaultValues,
  formSchema,
  additionalButtons,
}: {
  formSchema: T;
  defaultValues: z.infer<T>;
  formItems: {
    name: Path<z.infer<T>>;
    label: string;
    inputComp?: React.FunctionComponent<any>;
    options?: React.ComponentProps<'input'> & {
      [key: string]: any;
    };
  }[];
  additionalButtons?: React.ReactNode[];
}) {
  const pathname = usePathname();
  const searchParams = useSearchParams();
  const replace = useRouter().replace;

  const form = useForm<z.infer<typeof formSchema>>({
    resolver: zodResolver(formSchema),
    defaultValues,
  });

  const onSubmit = (values: z.infer<typeof formSchema>) => {
    const newSearchParams = new URLSearchParams(searchParams);
    for (const [key, value] of Object.entries(values)) {
      if (JSON.stringify(defaultValues[key]) === JSON.stringify(value))
        newSearchParams.delete(key);
      else
        newSearchParams.set(
          key,
          typeof value === 'string' ? value : JSON.stringify(value),
        );
    }
    newSearchParams.has('page') && newSearchParams.set('page', '1');
    replace(`${pathname}?${newSearchParams.toString()}`);
  };

  return (
    <Form {...form}>
      <form
        onSubmit={form.handleSubmit(onSubmit)}
        className="flex items-end justify-between"
      >
        <div className="flex flex-wrap gap-3">
          {formItems.map((item) => {
            const Comp = item.inputComp;
            return (
              <FormField
                key={item.label}
                control={form.control}
                name={item.name}
                render={({ field }) => (
                  <FormItem>
                    <FormLabel>{item.label}</FormLabel>
                    <FormControl>
                      {Comp ? (
                        <Comp
                          onChange={field.onChange}
                          value={field.value}
                          {...item.options}
                        />
                      ) : (
                        <Input
                          placeholder={item.label}
                          {...field}
                          {...item.options}
                        />
                      )}
                    </FormControl>
                    <FormMessage />
                  </FormItem>
                )}
              />
            );
          })}
        </div>
        <div className="flex gap-3 justify-end">
          <Button type="submit" variant="outline" onClick={() => form.reset()}>
            重置
          </Button>
          <Button type="submit">搜索</Button>
          {additionalButtons}
        </div>
      </form>
    </Form>
  );
}
